namespace soccer {

    //物理控制器
    export class FrontPhyController extends hjc.Controller {
        public static Ins: FrontPhyController
        private _world: Box2D.Dynamics.b2World
        private _debug: Box2D.Dynamics.b2DebugDraw
        private _ball: helper.PhyObject
        private _tapA: helper.PhyObject
        private _tapB: helper.PhyObject
        private _start: boolean = false
        private _contactListener: Box2D.Dynamics.b2ContactListener
        private _contactFilter: Box2D.Dynamics.b2ContactFilter

        constructor() {
            super()
            FrontPhyController.Ins = this
            game.timer.registerBySeconds(1 / helper.step, this.loop, this)

            this._contactListener = new Box2D.Dynamics.b2ContactListener()
            this._contactListener.BeginContact = function (contact: Box2D.Dynamics.Contacts.b2Contact) {
                let bodyA = contact.GetFixtureA().GetBody().GetUserData()
                let bodyB = contact.GetFixtureB().GetBody().GetUserData()
                if (bodyA && bodyB) {
                    let phyObjA = <helper.PhyObject>(bodyA)
                    let phyObjB = <helper.PhyObject>(bodyB)

                    if (phyObjA.isTap && phyObjB.isTap) {
                        contact.SetEnabled(false)
                        return
                    }

                    let ret = phyObjA.type + phyObjB.type
                    if (ret == helper.PhyObjectType.Ball + helper.PhyObjectType.DoorA) {
                        console.debug("AAAAAAA")
                    }
                    if (ret == helper.PhyObjectType.Ball + helper.PhyObjectType.DoorB) {
                        console.debug("BBBBBBB")
                    }
                }
            }

            this._contactFilter = new Box2D.Dynamics.b2ContactFilter()
            this._contactFilter.ShouldCollide = function (fixtureA: Box2D.Dynamics.b2Fixture, fixtureB: Box2D.Dynamics.b2Fixture): boolean {
                let bodyA = fixtureA.GetBody().GetUserData()
                let bodyB = fixtureB.GetBody().GetUserData()
                if (bodyA && bodyB) {
                    let phyObjA = <helper.PhyObject>(bodyA)
                    let phyObjB = <helper.PhyObject>(bodyB)
                    if (phyObjA.isTap && phyObjB.isTap) {
                        return false
                    }
                }
                return true
            }
        }

        public resetWorld(debugDisplay: egret.Sprite) {
            this._world = null
            this._debug = null
            this._start = false
            this._world = new Box2D.Dynamics.b2World(helper.NewVec2(0, 0), true)
            this._world.SetContactListener(this._contactListener)
            this._world.SetContactFilter(this._contactFilter)
            if (debugDisplay) {
                this._debug = new Box2D.Dynamics.b2DebugDraw()
                this._debug.SetSprite(debugDisplay);
                this._debug.SetDrawScale(helper.p2m);
                this._debug.SetLineThickness(1);
                this._debug.SetAlpha(0.8);
                this._debug.SetFillAlpha(0.5);
                this._debug.SetFlags(Box2D.Dynamics.b2DebugDraw.e_shapeBit);
                this._world.SetDebugDraw(this._debug);
            }

            this.initTable()
            this._start = true
        }

        public updateTapPosition(tap: helper.PhyObjectType, x, y: number) {
            x = x / helper.p2m
            y = y / helper.p2m
            let newPos = helper.NewVec2(x, y)
            if (this._tapA.type == tap) {
                this._tapA.targetPos = newPos
            } else if (this._tapB.type == tap) {
                this._tapB.targetPos = newPos
            }
        }

        private loop(p: hjc.TimeParam) {
            if (this._start == false) {
                return
            }
            this._tapA.beforeStep()
            this._tapB.beforeStep()
            this._world.Step(1 / helper.step, 4, 8);
            this._tapA.afterStep()
            this._tapB.afterStep()
            GameProxy.Ins.updateTapPos(this._tapA.Pos, this._tapB.Pos, this._ball.Pos)

            if (this._debug != null) {
                this._world.DrawDebugData();
            }
        }

        private initTable() {
            let x = 50
            let y = 100
            let w = 250
            let h = 1000
            let m = 150
            let l = 10
            let tapR = 60
            helper.createBox(this._world, w / 2 + x, l / 2 + y, w, l, true)
            helper.createBox(this._world, w / 2 + m + w + x, l / 2 + y, w, l, true)
            helper.createBox(this._world, l / 2 + x, h / 2 + y, l, h - l - l, true)
            helper.createBox(this._world, w + w + m - l / 2 + x, h / 2 + y, l, h - l - l, true)
            helper.createBox(this._world, w / 2 + x, h - l / 2 + y, w, l, true)
            helper.createBox(this._world, w / 2 + m + w + x, h - l / 2 + y, w, l, true)

            new helper.PhyObject(helper.PhyObjectType.DoorA, helper.createBox(this._world, w + m / 2 + x, y - l / 2, m, l, true))
            new helper.PhyObject(helper.PhyObjectType.DoorB, helper.createBox(this._world, w + m / 2 + x, y + h + l / 2, m, l, true))

            let fixtureDef = new Box2D.Dynamics.b2FixtureDef()
            fixtureDef.friction = 1
            fixtureDef.restitution = 0.6
            fixtureDef.density = 10
            this._ball = new helper.PhyObject(helper.PhyObjectType.Ball, helper.createCircle(this._world, 360, 600, 20, false, null, fixtureDef))
            this._ball.body.SetLinearDamping(1.8)
            this._ball.body.SetAngularDamping(1)

            let limitA = {
                x: x + l + tapR,
                y: y + l + tapR,
                width: 2 * w + m - 2 * tapR - 2 * l,
                height: (h - 2 * tapR) / 11 * 5,
                fillColor: Color.BLUE,
                fillAlpha: 0.2,
                lineAlpha: 0,
            }
            this.createTap(helper.PhyObjectType.TapA, tapR, 360, 300, limitA)
            game.scene(soccer.TableScene).DebugGroup.addChild(ui.drawRect(limitA))

            let limitB = limitA
            limitB.y = y + h - tapR - l - limitB.height
            limitB.fillColor = Color.YELLOW
            limitB.fillAlpha = 0.1
            this.createTap(helper.PhyObjectType.TapB, tapR, 370, 900, limitB)
            game.scene(soccer.TableScene).DebugGroup.addChild(ui.drawRect(limitA))

        }

        private createTap(type: helper.PhyObjectType, r: number, x, y: number, limit: { x: number, y: number, width: number, height: number }) {
            let mass = new Box2D.Collision.Shapes.b2MassData()
            let fixtureDef = new Box2D.Dynamics.b2FixtureDef()
            fixtureDef.friction = 1
            fixtureDef.restitution = 1
            fixtureDef.density = 1
            let tap = new helper.PhyTap(type, helper.createCircle(this._world, x, y, r, false, null, fixtureDef), limit.x, limit.y, limit.width, limit.height)
            tap.body.SetLinearDamping(0)
            tap.body.SetAngularDamping(0)
            if (helper.PhyObjectType.TapA == type) {
                this._tapA = tap
            } else if (helper.PhyObjectType.TapB == type) {
                this._tapB = tap
            }
        }

        private checkTapTouch(pos: Box2D.Common.Math.b2Vec2): boolean {
            pos.Subtract(this._ball.body.GetPosition())
            console.log(pos.Length() * helper.p2m)
            return true || (pos.Length() * helper.p2m < 50)
        }
    }
}